home *** CD-ROM | disk | FTP | other *** search
- #!/usr/bin/perl -w
- #
- # $Id: Connection.pm,v 1.33 2004/11/26 08:41:42 solovam Exp $
- #
- # This file is a part of gkismet
- #
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public License
- # as published by the Free Software Foundation; either version 2
- # of the License, or (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- #
-
- #
- # Connection class
- #
- package Connection;
-
- use IO::Socket;
- use IO::Select;
- use Gtk;
- use Misc;
- use Observable;
- use strict;
-
- my $timeout = 5;
-
- #
- # Inherit methods from Observable
- #
- @Connection::ISA = qw(Observable);
-
- #
- # Constructor
- #
- sub new
- {
- # Standard prologue
- my $type = shift;
- my $self = {};
- bless $self, $type;
-
- # Constructor arguments
- $self->{'gKismetApplication'} = shift;
- $self->{'host'} = shift;
- $self->{'port'} = shift;
-
- # Connect to server
- if(!$self->connect())
- {
- return(undef);
- }
-
- # Enable protocols
- $self->enableProtocols();
-
- # Init fields
- $self->{'network'} = {};
- $self->{'status'} = {};
- $self->{'info'} = {};
- $self->{'packet'} = {};
- $self->{'string'} = {};
- $self->{'gps'} = {};
- $self->{'time'} = {};
- $self->{'alert'} = {};
-
- return($self);
- }
-
- #
- # Destructor
- #
- sub DESTROY
- {
- my $self = shift;
- $self->disconnect();
- }
-
- #
- # Get socket
- #
- sub getSocket
- {
- my $self = shift;
- return $self->{'socket'};
- }
-
- #
- # Connect to server
- #
- sub connect
- {
- my $self = shift;
-
- $self->{'socket'} = IO::Socket::INET->new("PeerAddr" => $self->{'host'}, "PeerPort" => $self->{'port'}, "Proto" => "tcp", "Timeout" => $timeout);
- unless($self->{'socket'})
- {
- return(0);
- }
-
- # Register input handler
- my $inputId = Gtk::Gdk->input_add($self->getSocket()->fileno, 'read', sub {$self->readServer()}, $self->getSocket());
- $self->{'inputId'} = $inputId;
-
- # Is it a kismet server we connected to?
- unless($self->{'socket'}->getline() =~ /\*KISMET/)
- {
- $self->disconnect();
- return(0);
- }
-
- return(1);
- }
-
- #
- # Disconnect from server
- #
- sub disconnect
- {
- my $self = shift;
- if(defined $self->{'inputId'})
- {
- Gtk::Gdk->input_remove($self->{'inputId'});
- }
- if($self->{'socket'})
- {
- $self->{'socket'}->close();
- }
- }
-
- #
- # Enable default set of protocols to watch
- #
- sub enableProtocols
- {
- my $self = shift;
- my @protocols = qw(GPS INFO NETWORK CLIENT REMOVE ALERT STATUS);
- for my $p (@protocols)
- {
- $self->{'socket'}->print("!0 ENABLE $p *\n");
- }
- }
-
- #
- # Eanble strings
- #
- sub enableStrings
- {
- my $self = shift;
- $self->{'socket'}->print("!0 ENABLE STRING *\n");
- }
-
- #
- # Disable strings
- #
- sub disableStrings
- {
- my $self = shift;
- $self->{'socket'}->print("!0 REMOVE STRING\n");
- }
-
- #
- # Enable packets
- #
- sub enablePackets
- {
- my $self = shift;
- $self->{'socket'}->print("!0 ENABLE PACKET *\n");
- }
-
- #
- # Disable packets
- #
- sub disablePackets
- {
- my $self = shift;
- $self->{'socket'}->print("!0 REMOVE PACKET\n");
- }
-
- #
- # Ask server to print capabilities
- #
- sub askCaps
- {
- my $self = shift;
- my @protocols = qw(GPS INFO NETWORK CLIENT REMOVE ALERT STATUS STRING PACKET);
- for my $p (@protocols)
- {
- $self->{'socket'}->print("!0 CAPABILITY $p\n");
- }
- }
-
- #
- # Read and parse input
- #
- my $inReadServer = $false;
- sub readServer
- {
- my $self = shift;
-
- if($inReadServer)
- {
- return;
- }
- $inReadServer = $true;
-
- my $res = $self->{'socket'}->getline();
- if(!$res)
- {
- $self->notifyObservers({'changed' => 'disconnected'});
- }
- else
- {
- chomp($res);
- my($cmd, $data) = ($res =~ /\*([^:]+):\s+(.*)/);
-
- if($cmd eq 'GPS')
- {
- my @fields = qw(lat lon alt spd heading fix);
- my @values = Connection->oneSplit($data);
- $self->{'gps'} = Connection->makeHash(\@fields, \@values);
- $self->notifyObservers({'changed' => 'gps'});
- }
- elsif($cmd eq 'INFO')
- {
- my @fields = qw(networks packets crypt weak noise dropped rate cardquality cardpower cardnoise);
- my @values = Connection->oneSplit($data);
- $self->{'info'} = Connection->makeHash(\@fields, \@values);
- $self->notifyObservers({'changed' => 'info'});
- }
- elsif($cmd eq 'NETWORK')
- {
- my @fields = qw(bssid type ssid beaconinfo llcpackets datapackets cryptpackets weakpackets channel wep firsttime lasttime atype
- rangeip gpsfixed minlat minlon minalt minspd maxlat maxlon maxalt maxspd octets cloaked beaconrate maxrate
- manufkey manufscore quality signal noise bestquality bestsignal bestnoise bestlat bestlon bestalt agglat agglon
- aggalt aggpoints datasize turbocellnid turbocellmode turbocellsat carrierset maxseenrate encodingset decrypted dupeivpackets);
- my @values = Connection->oneSplit($data);
- my $bssid = $values[0];
- for(my $i = 0; $i <= $#fields; $i++)
- {
- $self->{'network'}{$bssid}{$fields[$i]} = defined $values[$i] ? $values[$i] : 0;
- }
- $self->notifyObservers({'changed' => 'network', 'bssid' => $bssid});
- }
- elsif($cmd eq 'CLIENT')
- {
- my @fields = qw(bssid mac type firsttime lasttime manufkey manufscore datapackets cryptpackets weakpackets gpsfixed minlat minlon
- minalt minspd maxlat maxlon maxalt maxspd agglat agglon aggalt aggpoints maxrate quality signal noise bestquality
- bestsignal bestnoise bestlat bestlon bestalt atype ip datasize maxseenrate encodingset decrypted);
- my @values = Connection->oneSplit($data);
- my($bssid, $mac) = @values[0,1];
- for(my $i = 0; $i <= $#fields; $i++)
- {
- $self->{'network'}{$bssid}{'client'}{$mac}{$fields[$i]} = defined $values[$i] ? $values[$i] : 0;
- }
- $self->notifyObservers({'changed' => 'client', 'bssid' => $bssid, 'mac' => $mac});
- }
- elsif($cmd eq 'REMOVE')
- {
- my $bssid = $data;
- if(defined $self->{'network'}{$bssid})
- {
- $self->notifyObservers({'changed' => 'remove', 'bssid' => $bssid});
- delete $self->{'network'}{$bssid};
- }
- }
- elsif($cmd eq 'ALERT')
- {
- my @fields = qw(sec usec header bssid source dest other channel text);
- my @values = Connection->oneSplit($data);
- $self->{'alert'} = Connection->makeHash(\@fields, \@values);
- $self->notifyObservers({'changed' => 'alert'});
- }
- elsif($cmd eq 'STATUS')
- {
- $self->{'status'} = $data;
- $self->notifyObservers({'changed' => 'status'});
- }
- elsif($cmd eq 'TIME')
- {
- $self->{'time'} = $data;
- $self->notifyObservers({'changed' => 'time'});
- }
- elsif($cmd eq 'PACKET')
- {
- # Should we kep more than one packet?
- my @fields = qw(type subtype timesec encrypted weak beaconrate sourcemac destmac bssid ssid prototype sourceip destip sourceport
- destport nbtype nbsource);
- my @values = Connection->oneSplit($data);
- $self->{'packet'} = Connection->makeHash(\@fields, \@values);
- $self->notifyObservers({'changed' => 'packet'});
- }
- elsif($cmd eq 'STRING')
- {
- # Should we kep more than one string?
- my @fields = qw(bssid sourcemac text);
- my @values = Connection->oneSplit($data);
- $self->{'string'} = Connection->makeHash(\@fields, \@values);
- $self->notifyObservers({'changed' => 'string'});
- }
- }
- $inReadServer = $false;
- }
-
- #
- # Make hash from an array of keys and values
- #
- sub makeHash
- {
- shift;
- my $keys = shift;
- my $values = shift;
- my %hash;
- for(my $i = 0; $i <= $#{$keys}; $i++)
- {
- $hash{$keys->[$i]} = defined $values->[$i] ? $values->[$i] : 0;
- }
- return \%hash;
- }
-
- #
- # Get port
- #
- sub port
- {
- my $self = shift;
- return $self->{'port'};
- }
-
- #
- # Get host
- #
- sub host
- {
- my $self = shift;
- return $self->{'host'};
- }
-
- #
- # Get network
- #
- sub getNetwork
- {
- my $self = shift;
- return $self->{'network'};
- }
-
- #
- # get status
- #
- sub getStatus
- {
- my $self = shift;
- return $self->{'status'};
- }
-
- #
- # Get info
- #
- sub getInfo
- {
- my $self = shift;
- return $self->{'info'};
- }
-
- #
- # Get GPS
- #
- sub getGps
- {
- my $self = shift;
- return $self->{'gps'};
- }
-
- #
- # Get alert
- #
- sub getAlert
- {
- my $self = shift;
- return $self->{'alert'};
- }
-
- #
- # Get time
- #
- sub getTime
- {
- my $self = shift;
- return $self->{'time'};
- }
-
- #
- # Get string
- #
- sub getString
- {
- my $self = shift;
- return $self->{'string'};
- }
-
- #
- # Get packet
- #
- sub getPacket
- {
- my $self = shift;
- return $self->{'packet'};
- }
-
- #
- # Split on space. \001 works as quotation symbol. Based on shellwords.pl
- #
- sub oneSplit
- {
- shift;
-
- ($_) = (@_);
- my(@words, $snippet, $field);
-
- s/^\s+//;
- while ($_ ne '')
- {
- $field = '';
- while(1)
- {
- if(s/^\001([^\001]*)\001//)
- {
- $snippet = $1;
- }
- elsif(s/^([^\s\001]+)//)
- {
- $snippet = $1;
- }
- else
- {
- s/^\s+//;
- last;
- }
- $field .= $snippet;
- }
- push(@words, $field);
- }
- return(@words);
- }
-
- 1;
-